package model;

import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.util.ArrayList;
import java.util.List;

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlTransient;

import util.CollectionChangeEvent;
import util.CollectionChangeListener;
import util.CollectionChangeSupport;

@XmlAccessorType(XmlAccessType.FIELD)
public class Statechart {

	public enum Property {
		COMPONENTS, NAME
	}

	private Long id;
	private User creator;
	private String name;

	@XmlTransient
	private List<StatechartComponent> components;
	private List<Long> componentIds;

	@XmlTransient
	protected PropertyChangeSupport propertyChangeSupport = new PropertyChangeSupport(
			this);

	@XmlTransient
	private CollectionChangeSupport<StatechartComponent> statechartComponentCollectionChangeSupport = new CollectionChangeSupport<StatechartComponent>(
			this);

	@SuppressWarnings("unused")
	private Statechart() {
	}

	// location is GLOBAL in mt4j for this component
	public Statechart(long id, User user, String name,
			List<StatechartComponent> components) {
		this.id = id;
		this.creator = user;
		this.name = name;
		this.components = components;
		this.componentIds = new ArrayList<Long>(this.components.size());
		for (StatechartComponent component : this.components) {
			componentIds.add(component.getId());
		}
	}

	public User getCreator() {
		return creator;
	}

	public List<StatechartComponent> getComponents() {
		return components;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		String oldName = this.name;
		this.name = name;
		propertyChangeSupport.firePropertyChange(Property.NAME.name(), oldName,
				this.name);
	}

	public void setComponents(List<StatechartComponent> components) {
		this.components = components;
		this.componentIds.clear();
		for (StatechartComponent component : this.components) {
			componentIds.add(component.getId());
		}
	}

	public Long getId() {
		return id;
	}

	public void addPropertyChangeListener(Property property,
			PropertyChangeListener listener) {
		this.propertyChangeSupport.addPropertyChangeListener(property.name(),
				listener);
	}

	public void removePropertyChangeListener(Property property,
			PropertyChangeListener listener) {
		this.propertyChangeSupport.removePropertyChangeListener(
				property.name(), listener);
	}

	protected void addStatechartComponent(StatechartComponent component) {
		this.components.add(component);
		this.componentIds.add(component.getId());
		this.statechartComponentCollectionChangeSupport.fireCollectionChanged(
				component, components.indexOf(component),
				CollectionChangeEvent.Type.ADD);
	}

	protected void removeStatechartComponent(StatechartComponent component) {
		if (components.contains(component)) {
			int index = components.indexOf(component);
			this.components.remove(component);
			this.componentIds.remove(component.getId());
			this.statechartComponentCollectionChangeSupport
					.fireCollectionChanged(component, index,
							CollectionChangeEvent.Type.REMOVE);
		}
	}

	public void addCollectionChangeListener(
			CollectionChangeListener<StatechartComponent> listener) {
		this.statechartComponentCollectionChangeSupport
				.addCollectionListener(listener);
	}

	public void removeCollectionChangeListener(
			CollectionChangeListener<StatechartComponent> listener) {
		this.statechartComponentCollectionChangeSupport
				.removeCollectionListener(listener);
	}

	public List<Long> getComponentIds() {
		return componentIds;
	}

	public void setComponentIds(List<Long> componentIds) {
		this.componentIds = componentIds;
	}
}
